package org.ifilm.controller;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.commons.lang3.StringUtils;
import org.ifilm.model.Project;
import org.ifilm.model.ProjectComment;
import org.ifilm.model.ProjectRating;
import org.ifilm.model.User;
import org.ifilm.model.UserJobPosting;
import org.ifilm.service.ProjectService;
import org.ifilm.service.UserServiceImpl;
import org.ifilm.util.GeneralConstants;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;

/**
 * 
 * Project Contoller. All requests about projects will be here
 * @author Mustafa Genç
 *
 */
@Controller
@RequestMapping("/project/**")
public class ProjectController {
	@Autowired
	private ProjectService projectService;
	
	@RequestMapping(value = "/createProject", method = {RequestMethod.POST, RequestMethod.GET})
	public ResponseEntity<Map<String, Object>> createProject(HttpServletRequest request, HttpServletResponse response) {
		Map<String, Object> responseBody = new HashMap<String, Object>();
		
		Project project = new Project();
		project.setProjectName(request.getParameter(GeneralConstants.projectName));
		project.setCountry(request.getParameter(GeneralConstants.projectCountry));
		project.setCity(request.getParameter(GeneralConstants.projectCity));
		project.setSubject(request.getParameter(GeneralConstants.projectSubject));
		project.setDescription(request.getParameter(GeneralConstants.projectDescription));
		project.setLanguage(request.getParameter(GeneralConstants.projectLanguage));
		project.setStartDate(request.getParameter(GeneralConstants.projectStartDate));
		project.setReleaseDate(request.getParameter(GeneralConstants.projectReleaseDate));
		
		String thumnbnailUrl = request.getParameter(GeneralConstants.projectThumbnailUrl);
		
		if (StringUtils.isNotBlank(thumnbnailUrl)) {
			project.setThumbnailUrl(thumnbnailUrl);
		}
		
		project.setCreator(getLoggedUser(request));
		project.setCreationTime(new Date());
		project.setUpdateTime(new Date());
		
		Project createdProject = projectService.createProject(project);
		
		if (createdProject != null) {
			responseBody.put("projectId", createdProject.getId());
		}
		
		return new ResponseEntity<Map<String, Object>>(responseBody, HttpStatus.OK);
	}
	
	@RequestMapping(value = "/getProject", method = {RequestMethod.POST, RequestMethod.GET})
	public ModelAndView getProject(@RequestParam(value = "pid") Long id, HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		ModelAndView result = new ModelAndView();
		
		Project project = projectService.getProject(id);
		if (project != null) {
			result.setViewName("/projectDetail.jsp");
			result.addObject("project", project);
			
			List<ProjectComment> comments = projectService.getComments(id);
			
			result.addObject("comments", comments);
		}
		
		User loggedUser = getLoggedUser(request);
		
		if (loggedUser != null) {
			ProjectRating projectRating = projectService.getProjectRate(id, loggedUser);
			if (projectRating != null) {
				result.addObject("rate", projectRating.getRate());
			} else {
				result.addObject("rate", 0);
			}
		}
		
		return result;
	}
	
	@RequestMapping(value = "/search", method = {RequestMethod.POST, RequestMethod.GET})
	public ModelAndView searchProjects(@RequestParam(value = "page") Integer page, @RequestParam(value = "max") Integer max,
			@RequestParam(value = "userType") String userTypeName, HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		ModelAndView result = new ModelAndView("/searchReturning.jsp");
		
		User loggedUser = getLoggedUser(request);
		
		if (userTypeName.contains("[")) {
			userTypeName = userTypeName.replaceAll("\\s","");
			userTypeName = userTypeName.substring(1, userTypeName.length() - 1);
		}
		
		List<String> userTypes = Arrays.asList(userTypeName.split(","));
		List<String> frontUserTypes = new ArrayList<String>();
		List<String> behindUserTypes = new ArrayList<String>();
		for (int i = 0; i < userTypes.size(); i++) {
			String type = userTypes.get(i);
			if (type.contains("actor")|| type.contains("actress")
					|| type.contains("dublour")) {
				frontUserTypes.add(type);
			} else {
				behindUserTypes.add(type);
			}
		}
		
		List<UserJobPosting> postingList = new ArrayList<UserJobPosting>();
		if (behindUserTypes != null && behindUserTypes.size() != 0) {
			//TODO: to use existing service method set page and max
			postingList = projectService.searchPostingsByUserType(1, 9999, behindUserTypes);
		}
		
		if (frontUserTypes != null && frontUserTypes.size() != 0) {
			List<UserJobPosting> frontList = projectService.searchByUserDetail(loggedUser);
			
			if (frontList != null && frontList.size() != 0) {
				postingList.addAll(frontList);
			}
		}
		
		if (postingList != null && postingList.size() != 0) {
			if ((page - 1) * max < postingList.size()) {
				int startIndex = (page - 1) * max == 0 ? 0 : ((page - 1) * max);
				postingList = postingList.subList(startIndex , (page * max) > postingList.size() ? postingList.size() : (page * max));
			} else {
				postingList = new ArrayList<UserJobPosting>();
			}
		}
		
		result.addObject("searchResultPostings", postingList);
		result.addObject("page", page);
		result.addObject("max", max);
		
		return result;
	}
	
	@RequestMapping(value = "/listProjects", method = {RequestMethod.POST, RequestMethod.GET})
	public ModelAndView listAllProjects(@RequestParam(value = "page") Integer page, @RequestParam(value = "max") Integer max,
			HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		ModelAndView result = new ModelAndView("/home.jsp");
		
		List<Project> projectList = projectService.listProjects(page, max);
		result.addObject("projects", projectList);
		result.addObject("page", page);
		result.addObject("max", max);
		
		return result;
	}
	
	@RequestMapping(value = "/listUserProjects", method = {RequestMethod.POST, RequestMethod.GET})
	public ModelAndView listUserProjects(@RequestParam(value = "userId") Long userId, @RequestParam(value = "page") Integer page, @RequestParam(value = "max") Integer max,
			HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		ModelAndView result = new ModelAndView("/userProjectsList.jsp");
		
		List<Project> projectList = projectService.listUserProjects(userId, page, max);
		result.addObject("projects", projectList);
		result.addObject("page", page);
		result.addObject("max", max);
		
		return result;
	}
	
	//for the userProfile.jsp page
	@RequestMapping(value = "/listUserProjectsForProfile", method = {RequestMethod.POST, RequestMethod.GET})
	public ModelAndView listUserProjectsForProfile(@RequestParam(value = "userId") Long userId, @RequestParam(value = "page") Integer page, @RequestParam(value = "max") Integer max,
			HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		ModelAndView result = new ModelAndView("/userProfile.jsp");
		
		List<Project> projectList = projectService.listUserProjects(userId, page, max);
		
		User user = projectService.getUserById(userId);
		
		if (user != null) {
			result.addObject(GeneralConstants.profileUser, user);
		}
		
		result.addObject("projects", projectList);
		result.addObject("page", page);
		result.addObject("max", max);
		
		return result;
	}
	
	@RequestMapping(value = "/getRecommendedPostings", method = {RequestMethod.POST, RequestMethod.GET})
	public ResponseEntity<Map<String, Object>> getRecommendedPostings(HttpServletRequest request, HttpServletResponse response) {
		Map<String, Object> responseBody = new HashMap<String, Object>();
		
		return new ResponseEntity<Map<String, Object>>(responseBody, HttpStatus.OK);
	}
	
	
	@RequestMapping(value = "/rate", method = {RequestMethod.POST, RequestMethod.GET})
	public ResponseEntity<Map<String, Object>> rateProject(@RequestParam(value = "projectId") Long projectId, @RequestParam(value = "rate") Integer rate,
			HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		Map<String, Object> responseBody = new HashMap<String, Object>();
		
		User loggedUser = getLoggedUser(request);
		
		if (loggedUser != null) {
			Project project = projectService.getProject(projectId);
			
			ProjectRating oldRating =  projectService.getProjectRate(projectId, loggedUser);
			
			if (oldRating == null) {
				ProjectRating projectRating = new ProjectRating();
				projectRating.setRate(rate);
				projectRating.setRatedProject(project);
				projectRating.setRater(loggedUser);
				
				projectService.rateProject(projectRating);
			} else {
				projectService.updateRate(project, oldRating, rate);
			}
			
			responseBody.put("rate", project.getAverageRate());
		}
		
		return new ResponseEntity<Map<String, Object>>(responseBody, HttpStatus.OK);
	}
	
	@RequestMapping(value = "/createProjectComment", method = {RequestMethod.POST, RequestMethod.GET})
	public ResponseEntity<Map<String, Object>> createProjectComment(@RequestParam Long projectId, @RequestParam String commentText, HttpServletRequest request, HttpServletResponse response) {
		Map<String, Object> responseBody = new HashMap<String, Object>();
		
		User loggedUser = getLoggedUser(request);
		
		if (loggedUser != null) {
			
			if (projectId != null && StringUtils.isNotBlank(commentText)) {
				ProjectComment projectComment = new ProjectComment();
				
				projectComment.setCommented(projectService.getProject(projectId));
				projectComment.setCommentor(loggedUser);
				projectComment.setComment(commentText);
				
				projectComment.setCreationTime(new Date());
				projectComment.setUpdateTime(new Date());
				
				projectComment = projectService.createProjectComment(projectComment);
				
				if (projectComment != null) {
					responseBody.put("status", "success");
					responseBody.put("user", loggedUser.getName() + " " + loggedUser.getSurname());
				} else {
					responseBody.put("status", "fail");
				}
			}
		}
		
		return new ResponseEntity<Map<String, Object>>(responseBody, HttpStatus.OK);
	}
	
	@RequestMapping(value = "/editProject", method = { RequestMethod.POST, RequestMethod.GET })
	public ModelAndView editProject(@RequestParam(value = "projectId") Long projectId, 
	HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		
		ModelAndView result = new ModelAndView();
		
		Project project = projectService.getProject(projectId);
		
		result.addObject(GeneralConstants.currentProject, project);
		result.setViewName("/editProject.jsp");
	
		return result;
	}
	
	@RequestMapping(value = "/saveEdit", method = { RequestMethod.POST, RequestMethod.GET })
	public ModelAndView saveEdit(@RequestParam(value = "projectId") Long projectId, 
	HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		
		ModelAndView result = new ModelAndView();
		
		Project project = projectService.getProject(projectId);
		
		if (project != null) {
			
			String projectThumbnailUrl = request.getParameter(GeneralConstants.projectThumbnailUrl);
			if (StringUtils.isNotBlank(projectThumbnailUrl)) {
				project.setThumbnailUrl(projectThumbnailUrl);
			}
			
			String projectName = request.getParameter(GeneralConstants.projectName);
			if (StringUtils.isNotBlank(projectName)) {
				project.setProjectName(projectName);
			}
			
			String projectCountry = request.getParameter(GeneralConstants.projectCountry);
			if (StringUtils.isNotBlank(projectCountry)) {
				project.setCountry(projectCountry);
			}
			
			String projectCity = request.getParameter(GeneralConstants.projectCity);
			if (StringUtils.isNotBlank(projectCity)) {
				project.setCity(projectCity);
			}
			
			String projectStartDate = request.getParameter(GeneralConstants.projectStartDate);
			if (StringUtils.isNotBlank(projectStartDate)) {
				project.setStartDate(projectStartDate);
			}
			
			String projectReleaseDate = request.getParameter(GeneralConstants.projectReleaseDate);
			if (StringUtils.isNotBlank(projectReleaseDate)) {
				project.setReleaseDate(projectReleaseDate);
			}
			
			String projectLanguage = request.getParameter(GeneralConstants.projectLanguage);
			if (StringUtils.isNotBlank(projectLanguage)) {
				project.setLanguage(projectLanguage);
			}
			
			String projectSubject = request.getParameter(GeneralConstants.projectSubject);
			if (StringUtils.isNotBlank(projectSubject)) {
				project.setSubject(projectSubject);
			}				
			
			String projectDescription = request.getParameter(GeneralConstants.projectDescription);
			if (StringUtils.isNotBlank(projectDescription)) {
				project.setDescription(projectDescription);
			}
			 
			project.setUpdateTime(new Date());
			
			//TODO
			projectService.editProject(project);
			
			result.addObject(GeneralConstants.currentProject, project);
			result.setViewName("/projectDetail.jsp");		
		}
	
		return result;
	}
	
	private User getLoggedUser(HttpServletRequest request) {
		HttpSession session = request.getSession();
		
		return (User) session.getAttribute(GeneralConstants.user);
	}
}